package controllers

import (
	//"3rd/errors"
	"3rd/utils"
	"github.com/astaxie/beego/session"
	redisess "github.com/astaxie/beego/session/redis"
	_ "github.com/garyburd/redigo/redis"
	"github.com/revel/revel"
	"time"
	"uc/app/models"
)

type Uc struct {
	Controller
}

var (
	globalSessions *session.Manager
)

func InitSession() {
	session.Register("redis1", &redisess.RedisProvider{})
	var err error
	globalSessions, err = session.NewManager("redis1", revel.Config.StringDefault("session", ""))
	if err != nil {
		panic(err)
	}
	go globalSessions.GC()
}

func (c Uc) GetCaptcha() revel.Result {
	// parse
	var media models.Media
	if err := models.ParseBodyAndValidate(c.body, &media); err != nil {
		return c.RenderResult(err)
	}

	// has reigstered?
//	user := models.User{Email: media.Media, Mobile: media.Media}
//	if err := user.MediaExists(); err != nil {
//		return c.RenderResult(err)
//	}

	// send captcha
	len := revel.Config.IntDefault("captcha.len", 4)
	expire := revel.Config.IntDefault("captcha.expire", 120)
	if err := media.SendCaptcha(len, expire); err != nil {
		return c.RenderResult(err)
	}

	return c.RenderResult(struct {
		RetryInterval int64 `json:"retryInterval"`
	}{RetryInterval: int64(expire)})
}

func (c Uc) Register() revel.Result {
	// parse
	type Req struct {
		Media    string `json:"media" valid:"Required"`
		Captcha  string `json:"captcha" valid:"Required"`
		UserName string `json:"userName"`
		Pwd      string `json:"pwd" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}

	// validate captcha
	if err := models.NewCaptcha(0, 0).Validate(req.Media, req.Captcha); err != nil {
		return c.RenderResult(err)
	}

	// register
	var user models.User
	if err := user.ResolveMedia(req.Media); err != nil {
		return c.RenderResult(err)
	}

	user.UserName = req.Media
	user.Qid, _ = utils.Qid()
	user.Password = req.Pwd
	user.Created = time.Now().Unix()
	if err := user.Register(); err != nil {
		return c.RenderResult(err)
	}

	// create session
	//	sess, _ := globalSessions.SessionStart(c.Response.Out, c.Request.Request)
	//	defer sess.SessionRelease(c.Response.Out)
	//	sess.Set("qid", user.Qid)

	return c.RenderResult(struct {
		UserName string `json:"userName"`
		Qid      string `json:"qid"`
	}{user.UserName, user.Qid})
}

func (c Uc) RegisterSilently() revel.Result {
	// parse
	var user models.User
	if err := utils.ParseBodyAndValidate(c.body, &user); err != nil {
		return c.RenderResult(err)
	}

	user.Qid, _ = utils.Qid()
	// TODO: pwd encrypt
	user.Created = time.Now().Unix()

	if err := user.Register(); err != nil {
		return c.RenderResult(err)
	}

	// create session
	//	sess, _ := globalSessions.SessionStart(c.Response.Out, c.Request.Request)
	//	 defer sess.SessionRelease(c.Response.Out)
	//	sess.Set("qid", user.Qid)

	return c.RenderResult(struct {
		UserName string `json:"userName"`
		//Qid      string `json:"qid"`
	}{user.UserName})
}

func (c Uc) Login() revel.Result {
	// parse
	type Req struct {
		UserName string `json:"userName" valid:"Required"`
		Pwd      string `json:"pwd" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}

	// validate user
	user := models.User{UserName: req.UserName, Password: req.Pwd}
	qid, err := user.GetQidByName()
	if err != nil {
		return c.RenderResult(err)
	}

	// create session
	sess, _ := globalSessions.SessionStart(c.Response.Out, c.Request.Request)
	defer sess.SessionRelease(c.Response.Out)
	sess.Set("qid", qid)

	return c.RenderResult(struct {
		Qid string `json:"qid"`
		Sid string `json:"sid"`
	}{qid, sess.SessionID()})
}

func (c Uc) Logout() revel.Result {
	// parse
	var req models.QS
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	// clean session
	globalSessions.SessionDestroy(c.Response.Out, c.Request.Request)

	return c.RenderResult(nil)
}

func (c Uc) Validate() revel.Result {
	// parse
	var req models.QS
	if err := utils.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	// TODO:
//	if sessStore, err := globalSessions.GetSessionStore(req.Sid); err != nil || sessStore.Get("qid") != req.Qid {
//		revel.ERROR.Println("-------------------->",err, sessStore, req.Qid, sessStore.Get("qid"))
//		return c.RenderResult(errors.New(models.InvalidSession, err))
//	}
	return c.RenderResult(nil)
}

func (c Uc) Status() revel.Result {
	// parse
	type Req struct {
		Qid string `json:"qid" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	//	if sessStore, err := globalSessions.GetSessionStore(req.Sid);
	//	err != nil || sessStore.Get("qid") != req.Qid {
	//		return c.RenderResult(errors.New(models.InvalidSession, "invalid session"))
	//	}
	return c.RenderResult(nil)
}

func (c Uc) HasRegistered() revel.Result {
	// parse
	type Req struct {
		UserName string `json:"userName" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	//	if sessStore, err := globalSessions.GetSessionStore(req.Sid);
	//	err != nil || sessStore.Get("qid") != req.Qid {
	//		return c.RenderResult(errors.New(models.InvalidSession, "invalid session"))
	//	}
	user := models.User{}
	return c.RenderResult(user.UserExists(req.UserName))
}

func (c Uc) ResetPwd() revel.Result {
	// parse
	type Req struct {
		Media    string `json:"media" valid:"Required"`
		Captcha  string `json:"captcha" valid:"Required"`
		Pwd      string `json:"pwd" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	// validate captcha
	if err := models.NewCaptcha(0, 0).Validate(req.Media, req.Captcha); err != nil {
		return c.RenderResult(err)
	}
	user := models.User{}
	if err := user.ResolveMedia(req.Media); err != nil {
		return c.RenderResult(err)
	}
	return c.RenderResult(user.ResetPwd(req.Pwd))
}

func (c Uc) ModifyPwd() revel.Result {
	// parse
	type Req struct {
		models.QS `,inline valid:"Required"`
		OldPwd    string `json:"oldPwd" valid:"Required"`
		NewPwd  string `json:"newPwd" valid:"Required"`
	}
	var req Req
	if err := models.ParseBodyAndValidate(c.body, &req); err != nil {
		return c.RenderResult(err)
	}
	user := models.User{Qid: req.Qid, Password: req.OldPwd}
	return c.RenderResult(user.ModifyPwd(req.NewPwd))
}
